import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.Socket;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Scanner;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

public class GUI extends JFrame implements ActionListener
{
        static String userName = "";
        static String deleteMessage;
        public static String recipent;
        JTextArea messageArea, replyText;
        JButton compose, send, inbox, delete, exit, attachment;
		static JButton showFileImage;
		static JButton play;
		static JButton stop;
		static JButton loop;
        static JLabel userLoggedIn;
        public JPanel menubar, message, reply;
        static PrintWriter output;
        PrintWriter replyTextServer;
        private static ObjectOutputStream outputStream;
        private static ObjectInputStream inputStream; 
        static Scanner networkInput;
        static JList messageList;
        static DefaultListModel emailList, emailist2;
        static Socket socket;
        static EmailCommands constantRefresh;
        static JFileChooser fileChooser = new JFileChooser();
        static File file, sendFile, recieveingFile;
        static Boolean sendingFile = false;
        static ArrayList<EmailCommands> messages = new ArrayList();
        public static void main (String[] args) throws IOException
        {
                networkInitialisation(); // initialise the connection to the server
                GUI frame = new GUI(); //creates a new gui on load
                frame.setTitle("You're logged in as " + userName); // sets the titlebar to a friendly logged in message
                frame.setSize(640, 480); // sets the size of the gui
                frame.setVisible(true); // makes the gui visible
                frame.setResizable(false); // makes the gui a fixed size that isn't changeable by the user
                retrieveMessages(); // calls a function that sends a retrieve command to he server
                JOptionPane.showMessageDialog(null, "Welcome " + userName); // outputs a friendly message saying the user is logged in
                
                while (true) // this loop checks for new email
                {
                        try 
                        {
                        	    constantRefresh = (EmailCommands) inputStream.readObject(); // readinobject to pull the emails from the server
                                messages.add(constantRefresh);
                                
                        } 
                        catch (IOException e) 
                        {
                                JOptionPane.showInputDialog("ERROR: Unable to read email object");
                        }
                        
                        catch (ClassNotFoundException e) 
                        {
                                JOptionPane.showInputDialog("ERROR: Please reinstall client");
                        }
                        
                        String message = "<html>" + "Sender: " + constantRefresh.getUsername() + "<br>" + "Message: " + constantRefresh.getMessage() + "</html>";
                        if(constantRefresh.clientCommand().equals("email"))
                        { 
                                emailList.addElement(message); // adds the email to the jlist
                        }
                        if(constantRefresh.clientCommand().equals("email+file"))
                        {
                        	   
                        	   String fileMessage = "<html>" + "Sender: " + constantRefresh.getUsername() + "<br>" + "Message: " + constantRefresh.getMessage() + "<br>" + "There is a file attached, click the button below to open it"+ " </html>" + constantRefresh.fileBytes();
                               emailList.addElement(fileMessage); // adds the email to the jlist
                               
                        }
                }
        }

        public GUI() // creates the gui and all it's elements
        {
                while (userName.equals(""))
                {
                        userName = JOptionPane.showInputDialog("Please enter a username to login");
                }
                
                setLayout(new BorderLayout());
                reply = new JPanel();
                message = new JPanel();
                menubar = new JPanel();
                menubar.setLayout(new FlowLayout());
                menubar.setBackground(Color.blue);
                emailList = new DefaultListModel();
                messageList = new JList(emailList);
                messageList.setVisibleRowCount(13);
                messageList.contains(500, 500);
                replyText = new JTextArea(11,55);
                replyText.setWrapStyleWord(true);
                replyText.setLineWrap(true);
                message.setLayout(new GridLayout(1,1));
                inbox = new JButton("Your Inbox");
                delete = new JButton("Delete");
                exit = new JButton ("Exit the composer");
                compose = new JButton("Compose Email");
                send = new JButton("Send Email");
                attachment = new JButton("Send File");
                showFileImage = new JButton("Show File");
                send.setEnabled(false);
                send.setVisible(false);
                delete.setEnabled(false);
                inbox.addActionListener(this);
                delete.addActionListener(this);
                compose.addActionListener(this);
                send.addActionListener(this);
                attachment.addActionListener(this);
                showFileImage.addActionListener(this);
                
                
                add(message, BorderLayout.NORTH);
                add(menubar, BorderLayout.SOUTH);
                add(reply, BorderLayout.CENTER);
                message.add(new JScrollPane(messageList), BorderLayout.NORTH);
                menubar.add(compose);
                menubar.add(send);
                menubar.add(inbox);
                menubar.add(delete);
                menubar.add(attachment);
                menubar.add(showFileImage);
                reply.add(new JScrollPane(replyText));
                reply.setVisible(false);
                
                ListSelectionModel selectionHandler = messageList.getSelectionModel();
                selectionHandler.addListSelectionListener(new SharedListSelectionHandler());    
        }
        class SharedListSelectionHandler implements ListSelectionListener // makes the list selection and event handler
        {
                public void valueChanged(ListSelectionEvent arg0) 
                {
                        delete.setEnabled(true);
                }
                
        }
        
        public void actionPerformed(ActionEvent e) 
        {
                String Action = e.getActionCommand(); // gets the envent triggered
                if (Action.equals("Compose Email"))
                {
                        recipent = JOptionPane.showInputDialog("Please enter the user that you want to email");
                        reply.setVisible(true);
                        send.setVisible(true);
                        send.setEnabled(true);
                        compose.setVisible(false);
                        compose.setEnabled(false);
                        messageList.setVisibleRowCount(6);                      
                }
                
                if (Action.equals("Send Email"))
                {
                        reply.setVisible(false);
                        send.setVisible(false);
                        send.setEnabled(false);
                        compose.setVisible(true);
                        compose.setEnabled(true);
                        if (sendingFile)
                        {
                        	sendMessageWithFile();
                        }
                        else
                        {
                        	sendMessage();
                        }
                        retrieveMessages();
                        replyText.setText(null);
                        
                }
                if (Action.equals("Your Inbox"))
                {
                        reply.setVisible(false);
                        send.setVisible(false);
                        send.setEnabled(false);
                        compose.setVisible(true);
                        compose.setEnabled(true);
                        retrieveMessages();
                        
                }
                
                if (Action.equals("Delete"))
                {
                        reply.setVisible(false);
                        send.setVisible(false);
                        send.setEnabled(false);
                        compose.setVisible(true);
                        compose.setEnabled(true);
                        deleteMessage();
                        delete.setEnabled(false);
                }
                if (Action.equals("Send File"))
                {
                   selectFile();
                   sendingFile = true;
                }
                if (Action.equals("Show File"))
                {
                	int indexOfList = messageList.getSelectedIndex();
                	try {
                		showFile(indexOfList);
					} catch (IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
                }
        }
                
        public void sendMessage() // sends the message via an object to the server, this includes the username, the message, the reciopient, a command on the server to save and a blank index.
        {          
        	String no = "No file";
            EmailCommands sendEmail = new EmailCommands(userName, replyText.getText() , recipent, "send", 0, null, sendingFile.toString());
            try 
            {
                    outputStream.writeObject(sendEmail);
            } 
            catch (IOException e) 
            {
                    JOptionPane.showMessageDialog(null, "ERROR: Problem sending the email");
            }
                
        }
        public void sendMessageWithFile()
        {
        	EmailCommands sendEmailWithAttachment = new EmailCommands(userName, replyText.getText() , recipent, "file", 0, file, file.getName());
            try 
            {
                    outputStream.writeObject(sendEmailWithAttachment);
                    JOptionPane.showMessageDialog(null, "Sending email with file");
                    sendingFile = false;
                    file = null;
            } 
            catch (IOException e) 
            {
                    JOptionPane.showMessageDialog(null, "ERROR: Problem sending the email");
            }
        }
        public static void retrieveMessages() // this sends a command to the server asking it to retreieve all the emails from server based on the username of the client
        {
                emailList.clear();
                messages.clear();
                EmailCommands retrieveCommand = new EmailCommands(userName, null, null, "retreieve", 0, null, null);
                try 
                {
                        outputStream.writeObject(retrieveCommand);
                } 
                catch (IOException e) 
                {
                        JOptionPane.showMessageDialog(null, "ERROR: Problem getting the email");
                }
        }
        
        public static void networkInitialisation() // initialisation the network connection to the server
        {
                InetAddress host = null;
                final int PORT = 12349;

                try
                {
                        host = InetAddress.getLocalHost();
                        socket = new Socket(host, PORT);
                        outputStream = new ObjectOutputStream(socket.getOutputStream());
                        inputStream = new ObjectInputStream(socket.getInputStream());
                }
                catch(UnknownHostException uhEx)
                {
                        JOptionPane.showMessageDialog(null, "No server found");
                } 
                catch (IOException e) 
                {
                        e.printStackTrace();
                }
                
        }
        
        public void deleteMessage() // deletes the message based on the the text of the message that is in the messageList
        {
                
                int indexID = messageList.getSelectedIndex();
                String messageToDelete = (String) messageList.getSelectedValue();
                JOptionPane.showMessageDialog(null, messageToDelete);
                EmailCommands deleteEmail = new EmailCommands(null, messageToDelete, null, "delete", indexID, null, null);
                try 
                {
                        outputStream.writeObject(deleteEmail);
                        emailList.removeElementAt(indexID);
                } 
                catch (IOException e) 
                {
                        JOptionPane.showMessageDialog(null, "ERROR: Can not delete selected email. Please try again later.");
                }
        }
        
        public void selectFile()
        {
         int retval = fileChooser.showOpenDialog(null);
         if (retval == JFileChooser.APPROVE_OPTION) 
         {
             //... The user selected a file, get it, use it.
             file = fileChooser.getSelectedFile();
         }
         JOptionPane.showMessageDialog(null, "The file " + file.getName() + " has been added");
        }
        
        public static void showImage(EmailCommands image) throws IOException
        {
        	recieveingFile = image.fileBytes();
	        BufferedImage imageToView;
	        imageToView = ImageIO.read(recieveingFile);
	        JFrame frame = new JFrame();
	        JLabel label = new JLabel(new ImageIcon(imageToView));
	        frame.getContentPane().add(label, BorderLayout.CENTER);
	        frame.pack();
	        frame.setVisible(true);
        }
    	
		@SuppressWarnings("deprecation")
		public static void audioPlayer(EmailCommands audio) throws MalformedURLException
        {	
        	URI uri = audio.fileBytes().toURI();
			
        	AudioClip clip;
        	try
        	{
        		URL url = uri.toURL();
        		clip = Applet.newAudioClip(url);
        		clip.play();
        	}
        	
        	catch (MalformedURLException badURL)
        	{
        		JOptionPane.showMessageDialog(null, "The file is corrupted, it can not be view or played");
        	}
        }
		
		public void showFile(int indexOfFile) throws IOException
		{
            JOptionPane.showMessageDialog(null, indexOfFile);
            EmailCommands file = messages.get(indexOfFile);
            JOptionPane.showMessageDialog(null, file.fileName());
            if (file.fileName().endsWith(".JPG") || file.fileName().endsWith(".jpg"))
            {   
         	   showFileImage.setVisible(true);
         	   showImage(file);
            }
            else if (file.fileName().endsWith(".au"))
            {
         	   audioPlayer(file);
            }
		}
}
    
